//
// Created by HZWei on 2023/9/26.
//  指针

#include "io_utils.h"
#include <stdio.h>


int *pInt1;

void wild_pointer(){
    int p = 23;
    pInt1 = &p;
}


int main() {


    int a;
    scanf("%d:", &a);
    // 取址运算符， &变量名 即数据内存地址，相当于一个门牌号一样，通常用一个十六进制来表示
    PRINT_HEX(&a);

    // 指针运算符
    // 内存地址赋值一个变量时，则为指针，在数据类型后面加*，即内存地址变量
    int *p = &a;
    PRINT_HEX(p); // 访问内存地址 即 &a

    // 指针占用的内存，在64位占8字节，32位占4字节
    PRINT_INT(sizeof(int *)); // 8
    // 访问指针变量的内存数据 在指针变量前加*
    PRINT_INT(*p); //  == a的值
    PRINT_INT(a);

     int **pp = &p;  // *pp ->  p

     // 修改指针的值
     *p = 20; // 相当于修改a的值
    PRINT_INT(*p);
    PRINT_INT(a);


    // 小技巧：const前面修饰的是什么，就表示只读的类型，前面指针运算符*，就是只读指针，如果是数据类型比如int 就是只读类型变量指针
    // 定义不可修改的指针 , 只读指针 ，不能修改内存地址
    int b = 0;
    int *const cp = &a;
    *cp = 20;  // ok 可以修改指针变量的值，即对象值
//    cp = &b; // error 不能修改指针

    // 定义不可修改指针变量的值，只读类型变量指针
    int const *cpp = &a;
//    *cpp = 20; // error, 不能修改指针变量的值
    cpp = &b; // ok 可以修改指针的值 ，即改门牌号

   // 定义只读指针、只读指针变量
   int const *const cccp = &a;
   // *cccp = 30;; // error
  //  cccp = &b; // error


  // 指针定义的注意事项，特殊指针
   // 1、不能硬编码赋值给指针
//   int *pInt = (int *) 0x61fe14; //error
//    PRINT_HEX(pInt);

// 2、空指针的用法
    int *pInt = NULL;
//    *pInt = 20; // error 不能修改空指针的值
//    pInt = &b; // 初始化指针
    if (pInt) {
        PRINT_INT(*pInt); // 在指针没有初始化时即NULL，不能访问指针的值，需要判断
    }

 // 3、避免野指针，就是内存被回收了，通常在函数内的自动变量

    wild_pointer();
    PRINTLNF("野指针：%d",*pInt1);

    return 0;
}

